import test from "ava"
import ceno from "../src"
import { createHttpTestServer } from "./helpers/create-http-test-server"

test('请求拦截器 - 修改请求头', async (t) => {
    t.plan(2)
    const server = await createHttpTestServer()

    server.get('/', (request, response) => {
        response.json({
            author: request.headers['author'],
            cake: request.headers['cake']
        })
    })

    const api = ceno.create({
        interceptors: {
            request: {
               onFulfilled: (request) => {
                request.headers.set('author', 'lihainuo')
                request.headers.set('cake', 'cake')
                return request
               } 
            }
        }
    })

    interface Result {
        author: string
        cake: string
    }

    const data = await api.get<Result>(server.url).json()

    t.is(data.author, 'lihainuo')
    t.is(data.cake, 'cake')

    await server.close()
})

test('响应拦截器 - 修改响应体', async (t) => {
    const server = await createHttpTestServer()

    server.get('/', (request, response) => {
        response.json({ cake: 'cake' })
    })

    const api = ceno.create({
        interceptors: {
            response: {
                onFulfilled: async (response) => {
                    const data = await response.json()
                    const modifiedResponse = new Response(
                        JSON.stringify({ ...data, intercepted: true }),
                        {
                            status: response.status,
                            statusText: response.statusText,
                            headers: response.headers
                        }
                    )
                    return modifiedResponse
                }
            }
        }
    })

    const data = await api.get(server.url).json()

    t.deepEqual(data, {
        cake: 'cake',
        intercepted: true
    })

    await server.close()
})

test('响应拦截器 - 状态码转换', async (t) => {
    t.plan(2)
    const server = await createHttpTestServer()

    server.get('/404', (request, response) => {
        response.status(404).json({
            error: 'Not Found'
        })
    })

    const api = ceno.create({
        throwHttpErrors: false, // 不自动抛出 HTTP 错误
        interceptors: {
            response: {
                onFulfilled: async (response) => {
                    if (response.status === 404) {
                        // 404 -> 200
                        return new Response(
                            JSON.stringify({ converted: true, original: 404 }),
                            {
                                status: 200,
                                statusText: 'OK',
                                headers: response.headers
                            }
                        )
                    }
                    return response
                }
            }
        }
    })

    const response = await api.get(server.url + '/404')
    const data = await response.json()

    t.is(response.status, 200)
    t.deepEqual(data, {
        converted: true,
        original: 404
    })

    await server.close()
})

test('多个请求拦截器按顺序执行', async (t) => {
    t.plan(4)
    const server = await createHttpTestServer()
    const executionOrder: string[] = []

    server.get('/', (request, response) => {
        response.json({
            header1: request.headers['one'],
            header2: request.headers['two'],
            header3: request.headers['three']
        })
    })

    const api = ceno.create({
        interceptors: {
            request: [
                {
                    onFulfilled: (request) => {
                        request.headers.set('one', 'one')
                        executionOrder.push('one')
                        return request
                    }
                },
                {
                    onFulfilled: (request) => {
                        request.headers.set('two', 'two')
                        executionOrder.push('two')
                        return request
                    }
                },
                {
                    onFulfilled: (request) => {
                        request.headers.set('three', 'three')
                        executionOrder.push('three')
                        return request
                    }
                }
            ]
        }
    })

    interface Result {
        header1: string
        header2: string
        header3: string
    }

    const data = await api.get<Result>(server.url).json()

    t.deepEqual(executionOrder, ['one', 'two', 'three'])

    t.is(data.header1, 'one')
    t.is(data.header2, 'two')
    t.is(data.header3, 'three')

    await server.close()
})

test('异步拦截器正确执行', async (t) => {
    const server = await createHttpTestServer()
    
    server.get('/', (request, response) => {
        response.json({
            token: request.headers['authorization']
        })
    })

    const api = ceno.create({
        interceptors: {
            request: {
                onFulfilled: async (request) => {
                    // 模拟异步操作
                    await new Promise(resolve => setTimeout(resolve, 10))
                    const token = 'your-token'
                    request.headers.set('authorization', `Bearer ${token}`)
                    return request
                }
            }
        }
    })

    interface Result {
        token: string
    }

    const data = await api.get<Result>(server.url).json()

    t.is(data.token, 'Bearer your-token')

    await server.close()
})

test('拦截器错误处理 - onRejected 有时恢复', async (t) => {
    t.plan(2)
    const server = await createHttpTestServer()

    server.get('/', (request, response) => {
        response.json({
            success: true
        })
    })

    const api = ceno.create({
        interceptors: {
            request: {
                onFulfilled: () => {
                    throw new Error('Interceptor Error')
                },
                onRejected: (error) => {
                    // 恢复错误， 添加一个标记头
                    const request = new Request(server.url, {
                        headers: {
                            'x-intercepted': 'true'
                        }
                    })
                    return request
                }
            }
        }
    })

    interface Result {
        success: boolean
    }

    const response = await api.get<Result>(server.url)
    const data = await response.json()

    t.is(response.status, 200)
    t.deepEqual(data, {
        success: true
    })

    await server.close()
})

test('拦截器错误处理 - onRejected 没有时抛出错误', async (t) => {
    const server = await createHttpTestServer()

    const api = ceno.create({
        interceptors: {
            request: {
                onFulfilled: () => {
                    throw new Error('Interceptor failed without recovery')
                }
                // 没有 onRejected
            }
        }
    })

    await t.throwsAsync(
        async () => {
          await api.get(server.url);
        },
        { message: 'Interceptor failed without recovery' }
      );
    
      await server.close();
})

test('实例级拦截器独立工作', async (t) => {
    t.plan(2)
    const server = await createHttpTestServer()

    server.get('/', (request, response) => {
        response.json({
            instance: request.headers['instance'],
        })
    })

    // 创建带有实例级拦截器的实例
    const api = ceno.create({
        interceptors: {
            request: {
                onFulfilled: (request) => {
                    request.headers.set('instance', 'instance')
                    return request
                }
            }
        }
    })

    interface Result {
        instance?: string
    }

    // 普通请求（没有实例级拦截器）
    const normalResponse = await ceno.get<Result>(server.url)
    const normalData = await normalResponse.json()
    
    // 实例请求（有实例级拦截器）
    const instanceResponse = await api.get<Result>(server.url)
    const instanceData = await instanceResponse.json()
  
    t.is(normalData.instance, undefined);
    t.is(instanceData.instance, 'instance');
  
    await server.close()
})

test('临时级拦截器正确执行', async (t) => {
    t.plan(4)
    const server = await createHttpTestServer()

    server.get('/', (request, response) => {
        response.json({
            temp: request.headers['temp'],
            permanent: request.headers['permanent']
        })
    })

    const api = ceno.create({
        interceptors: {
            request: {
                onFulfilled: (request) => {
                    request.headers.set('permanent', 'permanent')
                    return request
                }
            }
        }
    })

    interface Result {
        temp?: string
        permanent?: string
    }    
    
    const data1 = await api.get<Result>(server.url, {
        interceptors: {
            request: {
                onFulfilled: (request) => {
                    request.headers.set('temp', 'temp')
                    return request
                }
            }
        }
    }).json()

    const data2 = await api.get<Result>(server.url).json()


    t.is(data1.temp, 'temp')
    t.is(data1.permanent, 'permanent')
    t.is(data2.temp, undefined)
    t.is(data2.permanent, 'permanent')

    await server.close()
})

test('空拦截器数组正确处理', async (t) => {
    t.plan(2)
    const server = await createHttpTestServer()

    server.get('/', (request, response) => {
        response.json({
            success: true
        })
    })

    const api = ceno.create({
        interceptors: {
            request: [],
            response: []
        }
    })

    const response = await api.get(server.url)
    const data = await response.json()

    t.is(response.status, 200)
    t.deepEqual(data, {
        success: true
    })

    await server.close()
})

test('undefined 拦截器正确处理', async (t) => {
    t.plan(2)
    const server = await createHttpTestServer()

    server.get('/', (request, response) => {
        response.json({
            success: true
        })
    })

    const api = ceno.create({
        interceptors: {
            request: undefined,
            response: undefined
        }
    })

    const response = await api.get(server.url)
    const data = await response.json()

    t.is(response.status, 200)
    t.deepEqual(data, {
        success: true
    })

    await server.close()
})

test('请求和响应拦截器配合工作', async (t) => {
    t.plan(4)
    const server = await createHttpTestServer()

    server.post('/', (request, response) => {
        response.json({
            receivedAuth: request.headers['authorization'],
            receivedContentType: request.headers['content-type']
        })
    })

    const api = ceno.create({
        interceptors: {
            request: {
              onFulfilled: (request) => {
                // 添加认证头
                request.headers.set('authorization', 'Bearer interceptor-token');
                return request;
              }
            },
            response: {
              onFulfilled: async (response) => {
                const data = await response.json();
                // 添加响应处理时间戳
                const enhancedData = {
                  ...data,
                  processedAt: new Date().toISOString(),
                  intercepted: true
                };
                
                return new Response(JSON.stringify(enhancedData), {
                  status: response.status,
                  statusText: response.statusText,
                  headers: response.headers
                });
              }
            }
          }
    })

    interface Result {
        receivedAuth: string
        receivedContentType: string
        intercepted: boolean
        processedAt: string
    }

    const response = await api.post<Result>(server.url, {
        json: {
            message: 'Hello, world!'
        }
    })

    const data = await response.json()

    t.is(response.status, 200)
    t.is(data.receivedContentType, 'application/json');
    t.true(data.intercepted);
    t.true(typeof data.processedAt === 'string');

    await server.close()
})

test('📦 性能测试 - 大量拦截器性能测试', async (t) => {
    const server = await createHttpTestServer()
    
    server.get('/', (request, response) => {
      response.json({ success: true })
    })
  
    // 创建 50 个拦截器
    const interceptors = Array.from({ length: 50 }, (_, i) => ({
      onFulfilled: (request: Request) => {
        request.headers.set(`x-interceptor-${i}`, `value-${i}`)
        return request
      }
    }))
  
    const api = ceno.create({
      interceptors: {
        request: interceptors
      }
    })
  
    const startTime = performance.now()
    const response = await api.get(server.url)
    const endTime = performance.now()
  
    // 验证所有拦截器都执行了
    t.is(response.status, 200)
    
    // 性能不应该过慢（这个阈值可以根据实际情况调整）
    const executionTime = endTime - startTime
    t.true(executionTime < 1000, `执行时间 ${executionTime}ms 过长`)
  
    await server.close()
})

test('📦 真实场景 - JWT 认证和自动刷新', async (t) => {
    const server = await createHttpTestServer()
    
    let tokenRefreshCount = 0
    
    server.get('/protected', (request, response) => {
      const auth = request.headers['authorization']
      if (auth === 'Bearer valid-token') {
        response.json({ data: 'protected-data' })
      } else {
        response.status(401).json({ error: 'Unauthorized' })
      }
    })
  
    const api = ceno.create({
      throwHttpErrors: false,
      interceptors: {
        request: {
          onFulfilled: (request) => {
            // 模拟添加 JWT token
            request.headers.set('authorization', 'Bearer valid-token')
            return request
          }
        },
        response: {
          onFulfilled: async (response) => {
            if (response.status === 401) {
              // 模拟 token 刷新
              tokenRefreshCount++
              
              // 返回一个成功的响应，模拟刷新后重试成功
              return new Response(
                JSON.stringify({ data: 'protected-data', refreshed: true }),
                { status: 200, headers: response.headers }
              )
            }
            return response
          }
        }
      }
    })

    interface Result {
        data: string
    }
  
    const response = await api.get<Result>(server.url + '/protected')
    const data = await response.json()
  
    t.is(response.status, 200)
    t.is(data.data, 'protected-data')
  
    await server.close()
})

test('extend 一次性继承拦截器：父影响子，子不影响父', async (t) => {
  t.plan(6)

  const server = await createHttpTestServer()

  server.get('/', (request, response) => {
    response.json({
      parent: request.headers['x-parent'],
      child: request.headers['x-child']
    })
  })

  // 父：注册父请求拦截器
  const parent = ceno.create()
  parent.interceptors.use({
    request: {
      onFulfilled: (req) => {
        req.headers.set('x-parent', '1')
        return req
      }
    }
  })

  // 子：extend（应克隆父当下的拦截器）
  const child = parent.extend()

  // 验证1：子请求具备父拦截器效果
  let d1 = await child.get<{ parent?: string; child?: string }>(server.url).json()
  t.is(d1.parent, '1')
  t.is(d1.child, undefined)

  // 子新增自己的拦截器
  child.interceptors.use({
    request: {
      onFulfilled: (req) => {
        req.headers.set('x-child', '1')
        return req
      }
    }
  })

  // 验证2：父请求不受子新增影响
  let d2 = await parent.get<{ parent?: string; child?: string }>(server.url).json()
  t.is(d2.parent, '1')
  t.is(d2.child, undefined)

  // 验证3：子请求同时包含父+子拦截器效果
  let d3 = await child.get<{ parent?: string; child?: string }>(server.url).json()
  t.is(d3.parent, '1')
  t.is(d3.child, '1')

  await server.close()
})